package com.iwhalecloud.bss.kite.cucc.order.util;

import com.google.common.collect.ImmutableMap;
import com.iwhalecloud.bss.kite.common.constant.DcPublicConsts;
import com.iwhalecloud.bss.kite.common.constant.KeyConsts;
import com.iwhalecloud.bss.kite.common.constant.ServiceOfferConsts;
import com.iwhalecloud.bss.kite.common.constant.SymbolConsts;
import com.iwhalecloud.bss.kite.common.util.KiteBeanUtils;
import com.iwhalecloud.bss.kite.common.util.KiteDateUtils;
import com.iwhalecloud.bss.kite.common.util.KiteStringUtils;
import com.iwhalecloud.bss.kite.dataservice.cache.DcPublicCache;
import com.iwhalecloud.bss.kite.dataservice.cache.DcSystemParamCache;
import com.iwhalecloud.bss.kite.dataservice.cache.ServiceOfferCache;
import com.iwhalecloud.bss.kite.dataservice.entity.OrderItem;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.IInst;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.OfferInst;
import com.iwhalecloud.bss.kite.dataservice.entity.inst.ProdInst;
import com.iwhalecloud.bss.kite.dataservice.entity.order.OrderItemChange;
import com.iwhalecloud.bss.kite.manager.enums.ActionType;
import com.iwhalecloud.bss.kite.manager.enums.InstType;
import com.iwhalecloud.bss.kite.manager.inst.KiteAttr;
import com.iwhalecloud.bss.kite.manager.inst.KiteProdInstFunc;
import com.iwhalecloud.bss.kite.manager.inst.change.KiteInstChange;
import com.iwhalecloud.bss.kite.manager.inst.change.KiteRelChange;
import com.iwhalecloud.bss.kite.manager.inst.graph.IRelType;
import com.iwhalecloud.bss.kite.manager.util.ManagerUtils;
import com.iwhalecloud.bss.kite.order.client.dto.OrderRequest;
import com.ztesoft.bss.base.staticdata.CoreDataInteract;
import com.ztesoft.bss.order.base.consts.IKeyValues;
import com.ztesoft.bss.order.base.consts.KeyValues;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;

public abstract class AcceptUtils {

    private static final Map<String, InstType> INST_TYPE_MAP = ImmutableMap.<String, InstType>builder()
        .put(KeyConsts.OFFER_TYPE_10, InstType.BASE_OFFER_INST)
        .put(KeyConsts.OFFER_TYPE_11, InstType.MAIN_OFFER_INST)
        .put(KeyConsts.OFFER_TYPE_12, InstType.ADDITIONAL_OFFER_INST)
        .put(KeyConsts.OFFER_TYPE_13, InstType.PROMOTION_OFFER_INST)
        .put(KeyConsts.OFFER_TYPE_15, InstType.GIFT_OFFER_INST)
        .build();

    /**
     * 根据instStateChg 做反向构造
     *
     * @return
     */
    public static String withDrawInstStateChg(String instStateChg) {
        String withDrawInstChg = "";
        if ("KD".equals(instStateChg)) {
            withDrawInstChg = "DK";
        }
        else if ("DA".equals(instStateChg)) {
            withDrawInstChg = "AD";
        }
        else if ("AD".equals(instStateChg)) {
            withDrawInstChg = "DA";
        }
        else if ("AA".equals(instStateChg)) {
            withDrawInstChg = "AD";
        }
        else if ("DD".equals(instStateChg)) {
            withDrawInstChg = "DA";
        }
        else if ("XX".equals(instStateChg)) {
            withDrawInstChg = "XX";
        }
        return withDrawInstChg;
    }

    /**
     * 根据传入的INST_STATE_CHG计算动作类型
     *
     * @param inst_state_chg
     * @return
     */
    // inst_state_chg处理.
    public static String computAciontType(String inst_state_chg) {
        String instActionType = "";
        if ("AA/DA/KA/".indexOf(inst_state_chg) > -1) {
            instActionType = KeyValues.ACTION_TYPE_A;
        }
        else if ("KD/DD/AD/".indexOf(inst_state_chg) > -1) {
            instActionType = KeyValues.ACTION_TYPE_D;
        }
        else if ("DK/".indexOf(inst_state_chg) > -1) {
            instActionType = KeyValues.ACTION_TYPE_K;
        }
        return instActionType;
    }

    /**
     * Description: <br>
     * 根据订单变动信息还原实例属性值
     *
     * @taskId <br>
     * @param orderItemChange
     * @param Inst <br>
     */
    public static void inverse(OrderItemChange orderItemChange, IInst Inst) {
        // 还原实例动作类型
        // 正向获取变动
        // String instStateChg = AcceptUtils.withDrawInstStateChg(orderItemChange.getInstStateChg());
        // String actionType = AcceptUtils.computAciontType(instStateChg);
        String actionType = orderItemChange.getInstStateChg().substring(1, 2);
        if (actionType.equals(KeyConsts.ACTION_TYPE_A) || actionType.equals(KeyConsts.ACTION_TYPE_D)) {
            KiteBeanUtils.setValueByName(Inst, "actionType", actionType);
        }
        else {
            KiteBeanUtils.setValueByName(Inst, "actionType", KeyConsts.ACTION_TYPE_M);
        }

        // 还原属性值
        if (KiteStringUtils.equals("XX", orderItemChange.getInstStateChg())) {
            String propertyName = KiteStringUtils.underlineToCamel(orderItemChange.getFieldName());
            KiteBeanUtils.setValueByName(Inst, propertyName, orderItemChange.getFieldValue());
        }
    }

    public static String computeInstChgByAction(String oldActionType, String actionType) {
        String instStateChg = "";
        if (StringUtils.isEmpty(oldActionType) && !KeyConsts.ACTION_CODE_D.equals(actionType)) {
            return "AA";
        }
        if (KeyValues.ACTION_TYPE_A.equals(oldActionType) && KeyValues.ACTION_TYPE_D.equals(actionType)) {
            instStateChg = "AD";
        }
        else if (KeyValues.ACTION_TYPE_A.equals(oldActionType) && "M/A/".contains(actionType)) {
            //做不变化处理
            instStateChg = "XX";
        }
        else if (KeyValues.ACTION_TYPE_K.equals(oldActionType) && "M/A/".contains(actionType)) {
            //做不变化处理
            instStateChg = "XX";
        }
        else if (KeyValues.ACTION_TYPE_M.equals(oldActionType) && "M/A/".contains(actionType)) {
            //做不变化处理
            instStateChg = "XX";
        }
        else if (KeyValues.ACTION_TYPE_K.equals(oldActionType) && KeyValues.ACTION_TYPE_D.equals(actionType)) {
            //做删除处理
            instStateChg = "KD";
        }
        else if (KeyValues.ACTION_TYPE_M.equals(oldActionType) && KeyValues.ACTION_TYPE_D.equals(actionType)) {
            //做删除处理
            instStateChg = "KD";
        }
        else if (KeyValues.ACTION_TYPE_D.equals(oldActionType) && "M/A/".contains(actionType)) {
            //做不变化处理
            instStateChg = "DA";
        }
        else if (KeyValues.ACTION_TYPE_D.equals(oldActionType) && KeyValues.ACTION_TYPE_D.equals(actionType)) {
            //不处理
            return null;
        }
        return instStateChg;
    }

    /**
     * 是否套餐销售品或促销销售品或礼包
     */
    public static Boolean isOfferOrProOffer(String offerType) {
        if (KiteStringUtils.equalsAny(offerType, KeyValues.OFFER_KIND_1, KeyValues.OFFER_KIND_3, KeyConsts.OFFER_KIND_5)) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    /**
     * 获取服务提供标识
     */
    public static String getServiceOfferId(OrderRequest request, OrderItem orderItem) {
        String serviceOfferId = request.getServiceOfferId();
        // 获取订单对应的销售品实例
        OfferInst offerInst = request.getInstContainer().getOfferInstMap().get(orderItem.getObjId());

        // 如果是修正单，与原单服务一致
        if (CoreDataInteract.EVT_C_0003_1100.equals(request.getOrderContainer().getCustomerOrder().getOperType())) {
            return orderItem.getServiceOfferId();
        }

        String actionType = offerInst.getActionType();
        // 如果动作类型为"A"，则服务为新购
        if (KiteStringUtils.isEqual(ActionType.A.name(), actionType)) {
            return ServiceOfferCache.getServOfferIdByAskFlow(KeyValues.XSP_XINGOU);
        }

        // 如果动作类型为"M"，计算实例修改的服务提供
        if (KiteStringUtils.equalsAny(actionType, ActionType.M.name(), ActionType.K.name())) {
            return getServiceOfferIdByModInst(request, offerInst);
        }

        // 如果动作类型为"D",计算实例删除的服务提供
        if (KiteStringUtils.isEqual(ActionType.D.name(), actionType)) {
            return getServiceOfferIdByDelInst(request, offerInst);
        }

        return serviceOfferId;
    }

    /**
     * 获取修改实例变动服务提供
     */
    private static String getServiceOfferIdByModInst(OrderRequest request, OfferInst offerInst) {
        String serviceOfferId = request.getServiceOfferId();
        String offerType = offerInst.getOfferType();

        // 默认服务提供
        String defaultServOfferId = ServiceOfferCache.getServOfferIdByAskFlow(KeyValues.XSP_XIUGAI);
        if (isOfferOrProOffer(offerType)) {
            defaultServOfferId = ServiceOfferCache.getServOfferIdByAskFlow(KeyValues.XSP_OFFERXIUGAI);
        }

        // 服务提供是订购，则返回默认服务
        if (KiteStringUtils.isEqual(serviceOfferId, ServiceOfferConsts.SERVICE_OFFER_ORDER)) {
            return defaultServOfferId;
        }

        if (isOfferOrProOffer(offerType)) {
            // 销售品实例为修改，配置中的服务提供需要修改默认的服务提供
            if (matchOrderItemServOfferIdByConfig(DcPublicConsts.DC_MOD_INST_ORDER_ITEM_SERV_STYPE,
                DcPublicConsts.DC_MOD_OFFER_SERV_CONFIG_PKEY, serviceOfferId)) {
                serviceOfferId = defaultServOfferId;
            }
        }
        else {
            // 基础销售品为修改,配置中的服务提供需要修改默认的服务提供
            if (matchOrderItemServOfferIdByConfig(DcPublicConsts.DC_MOD_INST_ORDER_ITEM_SERV_STYPE,
                DcPublicConsts.DC_MOD_PROD_SERV_CONFIG_PKEY, serviceOfferId)) {
                serviceOfferId = defaultServOfferId;
            }
        }

        return serviceOfferId;
    }

    /**
     * 获取删除实例变动服务提供
     */
    private static String getServiceOfferIdByDelInst(OrderRequest request, OfferInst offerInst) {
        String serviceOfferId = request.getServiceOfferId();

        // 基础销售品拆机服务提供计算
        if (KiteStringUtils.isEqual(offerInst.getOfferType(), IKeyValues.OFFER_KIND_0)) {
            // 获取拆机或退订的产品品服务提供(优先已拆机服务配置为准)
            if (matchOrderItemServOfferIdByConfig(DcPublicConsts.DC_DEL_INST_ORDER_ITEM_SERV_STYPE,
                DcPublicConsts.DC_DEL_PROD_SERV_CONFIG_PKEY, serviceOfferId)) {
                return serviceOfferId;
            }

            return ServiceOfferCache.getServOfferIdByAskFlow(KeyValues.XSP_CHAIJI);
        }
        else {
            // 获取拆机或退订的销售品服务提供(优先已拆机服务配置为准)
            if (matchOrderItemServOfferIdByConfig(DcPublicConsts.DC_DEL_INST_ORDER_ITEM_SERV_STYPE,
                DcPublicConsts.DC_DEL_OFFER_SERV_CONFIG_PKEY, serviceOfferId)) {
                return serviceOfferId;
            }
            // 套餐销售品退订服务提供计算
            return ServiceOfferCache.getServOfferIdByAskFlow(KeyValues.XSP_ZHUXIAO);
        }
    }

    /**
     * 通过DC_PUBLIC配置匹配订单项服务提供
     */
    private static Boolean matchOrderItemServOfferIdByConfig(String stype, String pkey, String servOfferId) {
        String codea = DcPublicCache.getCodea(stype, pkey);
        if (KiteStringUtils.isEmpty(codea)) {
            codea = getDefOrderItemServOfferId(stype, pkey);
        }
        if (KiteStringUtils.isIndexOf(codea, servOfferId, SymbolConsts.COMMA)) {
            return Boolean.TRUE;
        }
        else {
            return Boolean.FALSE;
        }
    }

    /**
     *
     * Description: <br>
     *  获取订单项服务提供计算默认配置
     * @author xiao.xuzhang<br>
     * @taskId <br>
     * @param stype
     * @param pkey
     * @return <br>
     */
    private static String getDefOrderItemServOfferId(String stype, String pkey) {
        if (KiteStringUtils.equals(stype, DcPublicConsts.DC_DEL_INST_ORDER_ITEM_SERV_STYPE)
            && KiteStringUtils.equals(pkey, DcPublicConsts.DC_DEL_PROD_SERV_CONFIG_PKEY)) {
            // 返回拆机服务
            return ",2951,";
        }
        else if (KiteStringUtils.equals(stype, DcPublicConsts.DC_DEL_INST_ORDER_ITEM_SERV_STYPE)
            && KiteStringUtils.equals(pkey, DcPublicConsts.DC_DEL_OFFER_SERV_CONFIG_PKEY)) {
            return "";
        }
        else if (KiteStringUtils.equals(stype, DcPublicConsts.DC_MOD_INST_ORDER_ITEM_SERV_STYPE)
            && KiteStringUtils.equals(pkey, DcPublicConsts.DC_MOD_OFFER_SERV_CONFIG_PKEY)) {
            return ",2951,2831,2567,12870,20170801,";
        }
        else if (KiteStringUtils.equals(stype, DcPublicConsts.DC_MOD_INST_ORDER_ITEM_SERV_STYPE)
            && KiteStringUtils.equals(pkey, DcPublicConsts.DC_MOD_PROD_SERV_CONFIG_PKEY)) {
            return ",2826,2567,2831,2951,20180613,20170801,";
        }
        return "";
    }

    /**
     * 判断是否群组功能产品(先通过paramField属性不为空来判断，不一定准)
     * @param prodInstFunc
     * @return
     */
    public static boolean isGroupProdInstFunc(KiteProdInstFunc prodInstFunc) {
        if (Objects.isNull(prodInstFunc)) {
            return false;
        }

        Map<String, KiteAttr> attrMap = prodInstFunc.getAttrMap();
        Set<Entry<String, KiteAttr>> entrySet = attrMap.entrySet();
        for (Entry<String, KiteAttr> entry : entrySet) {
            KiteAttr attr = entry.getValue();
            if (StringUtils.isNotBlank(attr.getParamField())) {
                return true;
            }
        }

        return false;
    }

    /**
     * 获取基础销售品订单主产品规格ID<br>
     *
     * @param request
     * @param orderItem
     * @return <br>
     */
    public static String getOrderItemProdId(OrderRequest request, OrderItem orderItem) {
        if (KiteStringUtils.equals(orderItem.getOfferKind(), KeyValues.OFFER_KIND_0)) {
            // 获取接入产品实例
            ProdInst prodInst = request.getInstContainer().getProdInstMap().get(orderItem.getObjId());
            if (Objects.nonNull(prodInst)) {
                return KiteStringUtils.defaultIfEmpty(prodInst.getProdId(), "-1");
            }
        }
        return "-1";
    }

    /**
     * 订单变动信息变动字段值转换映射处理
     *
     * @taskId <br>
     * @param fieldName
     * @return <br>
     */
    public static String transformOrderItemChangeField(String fieldName) {
        // 过户业务newOwnerCustId转换为owner_cust_id
        if (KiteStringUtils.equals(fieldName, KeyConsts.NEW_OWNER_CUST_ID)) {
            fieldName = KeyConsts.OWNER_CUST_ID;
        }

        return fieldName;
    }

    /**
     * 添加实例变动信息
     * @param orderRequest
     * @param instId
     * @param instType
     * @param actionType
     * @param fieldName
     * @param oldValue
     * @param newValue
     */
    public static void addInstChange(OrderRequest orderRequest, String instId, InstType instType, ActionType actionType,
        String fieldName, String oldValue, String newValue) {
        addInstChange(orderRequest, instId, instType, instId, instType, actionType, fieldName, oldValue, newValue);
    }

    /**
     * 添加实例变动信息
     * @param orderRequest
     * @param instId
     * @param instType
     * @param subInstId
     * @param subInstType
     * @param actionType
     * @param fieldName
     * @param oldValue
     * @param newValue
     */
    public static void addInstChange(OrderRequest orderRequest, String instId, InstType instType, String subInstId,
        InstType subInstType, ActionType actionType, String fieldName, String oldValue, String newValue) {
        if (!ObjectUtils.allNotNull(orderRequest, instType, subInstType, actionType)
            || StringUtils.isAnyBlank(instId, subInstId)) {
            return;
        }

        KiteInstChange instChange = new KiteInstChange();
        instChange.setInstId(instId);
        instChange.setInstType(instType);
        instChange.setSubInstId(subInstId);
        instChange.setSubInstType(subInstType);
        instChange.setActionType(actionType);
        instChange.setFieldName(fieldName);
        instChange.setOldValue(oldValue);
        instChange.setNewValue(newValue);

        String key = ManagerUtils.join(instChange.getSubInstType(), instChange.getSubInstId());
        orderRequest.getInstChangeMap().computeIfAbsent(key, k -> new ArrayList<>()).add(instChange);
    }

    /**
     * 添加关系变动信息
     * @param orderRequest
     * @param sourceInstId
     * @param sourceInstType
     * @param targetInstId
     * @param targetInstType
     * @param relType
     * @param fieldName
     * @param oldValue
     * @param newValue
     */
    public static void addRelChange(OrderRequest orderRequest, String sourceInstId, InstType sourceInstType,
        String targetInstId, InstType targetInstType, IRelType relType, String fieldName, String oldValue,
        String newValue) {
        if (!ObjectUtils.allNotNull(orderRequest, sourceInstType, targetInstType, relType)
            || StringUtils.isAnyBlank(sourceInstId, targetInstId, fieldName)) {
            return;
        }

        KiteRelChange relChange = new KiteRelChange();
        relChange.setSourceInstId(sourceInstId);
        relChange.setSourceInstType(sourceInstType);
        relChange.setTargetInstId(targetInstId);
        relChange.setTargetInstType(targetInstType);
        relChange.setRelType(relType);
        relChange.setFieldName(fieldName);
        relChange.setOldValue(oldValue);
        relChange.setNewValue(newValue);

        String key = ManagerUtils.join(relChange.getSourceInstType(), relChange.getSourceInstId());
        orderRequest.getRelChangeMap().computeIfAbsent(key, k -> new ArrayList<>()).add(relChange);
    }

    /**
    * 根据销售品类型获取InstType
    * @param offerType
    * @return
    */
    public static InstType getOfferInstType(String offerType) {
        if (StringUtils.isBlank(offerType)) {
            return null;
        }

        return INST_TYPE_MAP.get(offerType);
    }

    /**
    * 判断实例类型是否销售品实例
    * @param instType
    * @return
    */
    public static boolean isOfferInst(InstType instType) {
        if (Objects.isNull(instType)) {
            return false;
        }

        return INST_TYPE_MAP.values().contains(instType);
    }

    /**
     * 默认失效时间
     * @return
     */
    public static Date getDefaultExpDate() {
        String defaultExpDate = DcSystemParamCache.getDcParamVal(KeyConsts.DC_DEFAULT_END_TIME);
        defaultExpDate = StringUtils.isNotBlank(defaultExpDate) ? defaultExpDate : KeyConsts.DEFAULT_EXPIRED_DATE;
        return KiteDateUtils.parseStrToDate(defaultExpDate, KiteDateUtils.DATE_FORMAT);
    }

    /**
     * 获取实例的actionType(如果newActionType不为空，则取newActionType)
     * @param inst
     * @return
     */
    public static String getActionType(IInst inst) {
        if (Objects.isNull(inst)) {
            return "";
        }

        return StringUtils.isNotBlank(inst.getNewActionType()) ? inst.getNewActionType() : inst.getActionType();
    }

    /**
     * 如果实例的actionType=A，则修改newActionType的值
     * @param inst
     * @param actionType
     */
    public static void setActionType(IInst inst, String actionType) {
        if (Objects.isNull(inst)) {
            return;
        }

        if (isAddInst(inst)) {
            // 新装的实例不能修改actionType
            return;
        }

        if (Objects.equals(ActionType.A.name(), inst.getActionType())
            && !Objects.equals(ActionType.A.name(), actionType) && !Objects.equals(ActionType.D.name(), actionType)) {
            inst.setNewActionType(actionType);
        }
        else if (!(Objects.equals(ActionType.A.name(), actionType) && StringUtils.isNotBlank(inst.getActionType()))) {
            inst.setActionType(actionType);
        }

    }

    /**
     * 是否新增的实例
     * @param inst
     * @return
     */
    public static boolean isAddInst(IInst inst) {
        if (Objects.isNull(inst)) {
            return false;
        }

        return Objects.equals(ActionType.A.name(), inst.getActionType())
            && StringUtils.isBlank(inst.getNewActionType());
    }

    /**
     * 是否在途的实例
     * @param inst
     * @return
     */
    public static boolean isOnwayInst(IInst inst) {
        if (Objects.isNull(inst)) {
            return false;
        }

        return Objects.equals(ActionType.A.name(), inst.getActionType())
            && StringUtils.isNotBlank(inst.getNewActionType());
    }

    /**
     * 是否修改的实例<br>
     * (actionType == A && newActionType == M) || actionType == M
     * @param inst
     * @return
     */
    public static boolean isModifyInst(IInst inst) {
        if (Objects.isNull(inst)) {
            return false;
        }

        return (Objects.equals(ActionType.A.name(), inst.getActionType())
            && Objects.equals(ActionType.M.name(), inst.getNewActionType()))
            || Objects.equals(ActionType.M.name(), inst.getActionType());
    }
}
